package com.beiming.libra.service.impl;

import static com.beiming.libra.common.enums.ArbitrationCaseStatusEnum.APPLY_REVIEW;

import com.beiming.libra.domain.CaseUserRelation;
import com.beiming.libra.domain.dto.responsedto.CaseUserEditQueryResponseDTO;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.beiming.libra.common.enums.ArbitrationCaseBaseEnum;
import com.beiming.libra.common.enums.ArbitrationCaseLogUserStatusEnum;
import com.beiming.libra.common.enums.ArbitrationCaseLogWorkStatusEnum;
import com.beiming.libra.common.enums.ArbitrationCaseStatusEnum;
import com.beiming.libra.common.enums.CaseApplyEnum;
import com.beiming.libra.common.enums.CaseUserTypeEnum;
import com.beiming.libra.common.enums.SMSEnum;
import com.beiming.libra.common.mail.model.Email;
import com.beiming.libra.common.mail.service.impl.MailServiceImpl;
import com.beiming.libra.common.page.Page;
import com.beiming.libra.common.page.PageResult;
import com.beiming.libra.common.utils.BeanConvertUtils;
import com.beiming.libra.common.utils.CommonsUtils;
import com.beiming.libra.dao.ArbitrationBookAttachmentMapper;
import com.beiming.libra.dao.ArbitrationBusinessDisputesMapper;
import com.beiming.libra.dao.ArbitrationCaseLogMapper;
import com.beiming.libra.dao.ArbitrationCaseMapper;
import com.beiming.libra.dao.ArbitrationCaseUserMapper;
import com.beiming.libra.dao.CaseStatusMapper;
import com.beiming.libra.dao.CaseUserRelationMapper;
import com.beiming.libra.domain.ArbitrationBookAttachment;
import com.beiming.libra.domain.ArbitrationBusinessDisputes;
import com.beiming.libra.domain.ArbitrationCase;
import com.beiming.libra.domain.ArbitrationCaseBasic;
import com.beiming.libra.domain.ArbitrationCaseLog;
import com.beiming.libra.domain.ArbitrationCaseUser;
import com.beiming.libra.domain.CaseStatus;
import com.beiming.libra.domain.UserMessage;
import com.beiming.libra.domain.dto.requestdto.ArbitrationBusinessDisputesUpdateRequestDTO;
import com.beiming.libra.domain.dto.requestdto.ArbitrationCaseActionUpdateRequestDTO;
import com.beiming.libra.domain.dto.requestdto.ArbitrationCaseRequestDTO;
import com.beiming.libra.domain.dto.requestdto.ArbitrationCaseUpdateRequestDTO;
import com.beiming.libra.domain.dto.responsedto.ArbitrationBasicCaseUserResponseDTO;
import com.beiming.libra.domain.dto.responsedto.ArbitrationCaseBasicResponseDTO;
import com.beiming.libra.domain.dto.responsedto.ArbitrationCaseResponseDTO;
import com.beiming.libra.domain.dto.responsedto.ArbitrationCaseUserResponseDTO;
import com.beiming.libra.quartz.JobScheduleController;
import com.beiming.libra.quartz.PayCheckJob;
import com.beiming.libra.service.ArbitrationCaseService;
import com.beiming.libra.service.SMSService;
import com.beiming.libra.service.base.BaseServiceImpl;

import lombok.extern.slf4j.Slf4j;
import tk.mybatis.mapper.entity.Example;

/**
 * 案件信息查询
 *
 * @author zhangqi
 */
@Service
@Slf4j
public class ArbitrationCaseServiceImpl extends BaseServiceImpl<ArbitrationCase>
    implements ArbitrationCaseService<ArbitrationCase> {

  @Resource
  private ArbitrationCaseMapper arbitrationCaseMapper;
  @Resource
  private ArbitrationCaseUserMapper arbitrationCaseUserMapper;
  @Resource
  private ArbitrationBusinessDisputesMapper arbitrationBusinessDisputesMapper;
  @Resource
  private UserMessageServiceImpl userMessageServiceImpl;
  @Resource
  private ArbitrationCaseLogMapper arbitrationCaseLogMapper;
  @Resource
  private CaseStatusMapper caseStatusMapper;
  @Resource
  private SMSService smsService;
  @Resource
  private MailServiceImpl mailServiceImpl;
  @Resource
  private JobScheduleController jobScheduleController;
  @Resource
  private CaseUserRelationMapper caseUserRelationMapper;
  @Resource
  private ArbitrationBookAttachmentMapper rbitrationBookAttachmentMappera;
  @Resource
  private DocumentCreateServiceImpl documentCreateServiceImpl;

  /**
   * 案件查询列表
   */
  @Override
  public PageResult<ArbitrationCaseBasicResponseDTO> getArbitrationCaseBasicList(
      ArbitrationCaseRequestDTO arbitrationCaseReq, String userId) {
    PageResult<ArbitrationCaseBasicResponseDTO> list = new PageResult<ArbitrationCaseBasicResponseDTO>();
    Page page = new Page();
    // 设置排序字段
    String sortField = "";
    // 初始申请采用CREATE_TIME排序
    if (APPLY_REVIEW.getCode().equals(arbitrationCaseReq.getCaseStatus())) {
      sortField = ArbitrationCaseBaseEnum.CREATE_TIME_SORTFIELD.getCode();
      if (arbitrationCaseReq.getCreateStarTime() != null
          && arbitrationCaseReq.getCreateEndTime() != null) {
        arbitrationCaseReq.setCreateStarTime(
            arbitrationCaseReq.getStarTime() + " " + ArbitrationCaseBaseEnum.COMMON_START_TIME
                .getCode());
        arbitrationCaseReq.setCreateEndTime(
            arbitrationCaseReq.getEndTime() + " " + ArbitrationCaseBaseEnum.COMMON_END_TIME
                .getCode());
      }
    } else {
      sortField = ArbitrationCaseBaseEnum.UPDATE_TIME_SORTFIELD.getCode();
      if (arbitrationCaseReq.getUpdateStarTime() != null
          && arbitrationCaseReq.getUpdateEndTime() != null) {
        arbitrationCaseReq.setUpdateStarTime(
            arbitrationCaseReq.getStarTime() + " " + ArbitrationCaseBaseEnum.COMMON_START_TIME
                .getCode());
        arbitrationCaseReq.setUpdateEndTime(
            arbitrationCaseReq.getEndTime() + " " + ArbitrationCaseBaseEnum.COMMON_END_TIME
                .getCode());
      }
    }
    if (arbitrationCaseReq.getPageNo() != 0) {
      page.setPageNo(arbitrationCaseReq.getPageNo());
      page.setPageSize(arbitrationCaseReq.getPageSize());
    }
    arbitrationCaseReq.setSortField(sortField);
    arbitrationCaseReq.setUserId(userId);
    if (!StringUtils.isBlank(arbitrationCaseReq.getCaseStatus())) {
      arbitrationCaseReq.setCaseStatusArr(arbitrationCaseReq.getCaseStatus().split(","));
    }
    page.setTotalRecords(arbitrationCaseMapper.pageCount(arbitrationCaseReq));
    list.setPage(page);
    List<ArbitrationCaseBasicResponseDTO> arbitrationCaseBasicResponseDTOList = new ArrayList<>();
    List<ArbitrationCaseBasic> arbitrationCaseBasicList = arbitrationCaseMapper
        .getArbitrationCaseList(arbitrationCaseReq);
    for (ArbitrationCaseBasic acb : arbitrationCaseBasicList) {
      acb.setCaseTypeName(CaseApplyEnum.getName(Integer.parseInt(acb.getCaseType()), 1));
      acb.setCaseStatusCategory(
          ArbitrationCaseStatusEnum.getGroupId(acb.getCaseStatus()).toString());
      acb.setDisputeTypeName(CaseApplyEnum.getName(Integer.parseInt(acb.getDisputeType()), 2));
      ArbitrationCaseBasicResponseDTO acr = new ArbitrationCaseBasicResponseDTO();
      List<ArbitrationBasicCaseUserResponseDTO> app = new ArrayList<>();
      List<ArbitrationBasicCaseUserResponseDTO> resp = new ArrayList<>();
      acr.setArbitrationCaseBasic(acb);
      List<ArbitrationBasicCaseUserResponseDTO> abcuList = arbitrationCaseUserMapper
          .getArbitrationCaseBasicUserList(acb.getId());
      for (ArbitrationBasicCaseUserResponseDTO acu : abcuList) {
        if (acu.getCaseUserType().equalsIgnoreCase(CaseUserTypeEnum.APPLICANT.getCode())
            || acu.getCaseUserType().equalsIgnoreCase(CaseUserTypeEnum.AGENT_APPLICANT.getCode())) {
          app.add(acu);
        } else {
          resp.add(acu);
        }
      }
      acr.setApplicantList(app);
      acr.setRespondentList(resp);
      arbitrationCaseBasicResponseDTOList.add(acr);
    }
    list.setList(arbitrationCaseBasicResponseDTOList);
    log.info("案件列表《getArbitrationCaseList》总条数=" + list.getList().size());
    return list;
  }

  @Override
  public ArbitrationCaseResponseDTO getArbitrationCase(String id) {
    ArbitrationCaseResponseDTO acr = new ArbitrationCaseResponseDTO();
    List<ArbitrationCaseUserResponseDTO> app = new ArrayList<>();
    List<ArbitrationCaseUserResponseDTO> resp = new ArrayList<>();
    Example arbitrationCaseExample = new Example(ArbitrationCase.class, false);
    arbitrationCaseExample.createCriteria().andEqualTo("id", id);
    ArbitrationCase ac = arbitrationCaseMapper.selectOneByExample(arbitrationCaseExample);
    acr.setArbitrationCase(ac);
    List<ArbitrationCaseUserResponseDTO> abcuList = arbitrationCaseUserMapper
        .getArbitrationCaseUserList(ac.getId());
    for (ArbitrationCaseUserResponseDTO acu : abcuList) {
      if (acu.getUserType().equalsIgnoreCase(CaseUserTypeEnum.APPLICANT.getCode())
          || acu.getUserType().equalsIgnoreCase(CaseUserTypeEnum.AGENT_APPLICANT.getCode())) {
        app.add(acu);
      } else {
        resp.add(acu);
      }
    }
    acr.setApplicantList(app);
    acr.setRespondentList(resp);
    // 业务要素
    Example arbitrationBusinessDisputesExample = new Example(ArbitrationBusinessDisputes.class,
        false);
    arbitrationBusinessDisputesExample.createCriteria().andEqualTo("caseId", ac.getId());
    acr.setArbitrationBusinessDisputes(
        arbitrationBusinessDisputesMapper.selectOneByExample(arbitrationBusinessDisputesExample));

    acr.setCaseUserProxyList(caseUserRelationMapper.getUserProxyDetail(ac.getId()));

    Example arbitrationBookAttachmentExample = new Example(ArbitrationBookAttachment.class, false);
    arbitrationBookAttachmentExample.createCriteria().andEqualTo("caseId", ac.getId());
    acr.setDocumentList(
        rbitrationBookAttachmentMappera.selectByExample(arbitrationBookAttachmentExample));

    Example arbitrationCaseLogExample = new Example(ArbitrationCaseLog.class, false);
    arbitrationCaseLogExample.createCriteria().andEqualTo("caseId", ac.getId());
    List<String> aclList = new ArrayList<String>();
    arbitrationCaseLogMapper.selectByExample(arbitrationCaseLogExample)
        .forEach(arbitrationCaseLog -> aclList.add(arbitrationCaseLog.getCaseStatus()));
    acr.setCaseStatusList(aclList);

    return acr;
  }

  @Override
  public int updateArbitrationBusinessDisputes(
      ArbitrationBusinessDisputesUpdateRequestDTO abdUpdateDTO) {
    return arbitrationBusinessDisputesMapper
        .updateByPrimaryKeySelective(
            BeanConvertUtils.copyBean(abdUpdateDTO, ArbitrationBusinessDisputes.class));
  }

  @Override
  public int updateCaseBasicInfo(ArbitrationCaseUpdateRequestDTO acUpdateDTO) {
    return arbitrationCaseMapper
        .updateByPrimaryKeySelective(BeanConvertUtils.copyBean(acUpdateDTO, ArbitrationCase.class));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public int updateCaseStatusForWork(
      ArbitrationCaseActionUpdateRequestDTO arbitrationCaseActionUpdateRequestDTO) {
    /** TODO flowable 本开发周期不考虑 */
    String caseStatus = arbitrationCaseActionUpdateRequestDTO.getCaseStatus();
    String id = arbitrationCaseActionUpdateRequestDTO.getId();
    String caseNo = arbitrationCaseActionUpdateRequestDTO.getCaseNo();
    Example acuExample = new Example(ArbitrationCaseUser.class, false);
    acuExample.createCriteria().andEqualTo("caseId", id).andEqualTo("addUserStatus", "1");
    List<ArbitrationCaseUser> acuList = arbitrationCaseUserMapper.selectByExample(acuExample);
    if (!StringUtils.isBlank(caseStatus)) {
      String[] app = {CaseUserTypeEnum.APPLICANT.getCode(),
          CaseUserTypeEnum.AGENT_APPLICANT.getCode()};
      String[] resp = {CaseUserTypeEnum.RESPONDENT.getCode(),
          CaseUserTypeEnum.AGENT_RESPONDENT.getCode()};
      if (caseStatus.equalsIgnoreCase(ArbitrationCaseStatusEnum.APPLY_REJECT.getCode())) {
        this.sendNormalMessage(id, acuList,
            ArbitrationCaseLogUserStatusEnum.APPLY_REJECT.getName());
        this.addCaseLog(id, ArbitrationCaseLogUserStatusEnum.APPLY_REJECT.getName(), "0",
            caseStatus);
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.APPLY_REJECT.getName(), "1",
            caseStatus);
        this.sendSMSAndMail(id, caseNo, SMSEnum.SMS_APPLY_REJECT_TO_USER, app, false, null);
      } else if (caseStatus.equalsIgnoreCase(ArbitrationCaseStatusEnum.APPLY_MODIFY.getCode())) {
        this.sendNormalMessage(id, acuList,
            ArbitrationCaseLogUserStatusEnum.APPLY_MODIFY.getName());
        this.addCaseLog(id, ArbitrationCaseLogUserStatusEnum.APPLY_MODIFY.getName(), "0",
            caseStatus);
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.APPLY_MODIFY.getName(), "1",
            caseStatus);
        this.sendSMSAndMail(id, caseNo, SMSEnum.SMS_APPLY_MODIFY_TO_USER, app, false, null);
      } else if (caseStatus.equalsIgnoreCase(ArbitrationCaseStatusEnum.APPLY_SUC.getCode())) {
        this.sendNormalMessage(id, acuList, ArbitrationCaseLogUserStatusEnum.APPLY_SUC.getName());
        this.addCaseLog(id, ArbitrationCaseLogUserStatusEnum.APPLY_SUC.getName(), "0", caseStatus);
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.APPLY_SUC.getName(), "1", caseStatus);
        this.sendSMSAndMail(id, caseNo, SMSEnum.SMS_APPLY_REVIEW_SUCCESS_TO_USER, app, true,
            "1,2,3");
        try {
          jobScheduleController.scheduleJob(id, null, 2, PayCheckJob.class);
        } catch (SchedulerException e) {
          e.printStackTrace();
        }
      } else if (caseStatus
          .equalsIgnoreCase(ArbitrationCaseStatusEnum.EXECUTE_TOOK_ARBITRATOR.getCode())) {
        // 被申请人文书送达
        this.sendSMSAndMail(id, caseNo, SMSEnum.SMS_BEFORE_FILE_TO_RESPONDENT, resp, true, "4,5,6");
      } else if (caseStatus
          .equalsIgnoreCase(ArbitrationCaseStatusEnum.EXECUTE_ARBITRATOR_QUE.getCode())) {
        this.addCaseLog(id, ArbitrationCaseLogUserStatusEnum.EXECUTE_ARBITRATOR_QUE.getName(), "0",
            caseStatus);
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.EXECUTE_ARBITRATOR_QUE.getName(), "1",
            caseStatus);
        this.sendNormalMessage(id, acuList,
            ArbitrationCaseLogUserStatusEnum.EXECUTE_ARBITRATOR_QUE.getName());
      } else if (caseStatus
          .equalsIgnoreCase(ArbitrationCaseStatusEnum.CC_ARBITRATOR_REVIEW_SUC.getCode())) {
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.CC_ARBITRATOR_REVIEW_SUC.getName(),
            "1", caseStatus);
      } else if (caseStatus
          .equalsIgnoreCase(ArbitrationCaseStatusEnum.CC_SECRETARY_REVIEW_SUC.getCode())) {
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.CC_SECRETARY_REVIEW_SUC.getName(), "1",
            caseStatus);
      } else if (caseStatus
          .equalsIgnoreCase(ArbitrationCaseStatusEnum.CC_LEADER_REVIEW_SUC.getCode())) {
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.CC_LEADER_REVIEW_SUC.getName(), "1",
            caseStatus);
      } else if (caseStatus.equalsIgnoreCase(ArbitrationCaseStatusEnum.FILE_APP.getCode())) {
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.FILE_APP.getName(), "1", caseStatus);
      } else if (caseStatus.equalsIgnoreCase(ArbitrationCaseStatusEnum.FILE_REVIEW_SUC.getCode())) {
        this.addCaseLog(id, ArbitrationCaseLogWorkStatusEnum.FILE_REVIEW_SUC.getName(), "1",
            caseStatus);
      }
    }

    return arbitrationCaseMapper.updateByPrimaryKeySelective(
        BeanConvertUtils.copyBean(arbitrationCaseActionUpdateRequestDTO, ArbitrationCase.class));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public int updateCaseStatusForUser(
      ArbitrationCaseActionUpdateRequestDTO arbitrationCaseActionUpdateRequestDTO) {
    /** TODO flowable 本开发周期不考虑 */
    return arbitrationCaseMapper.updateByPrimaryKeySelective(
        BeanConvertUtils.copyBean(arbitrationCaseActionUpdateRequestDTO, ArbitrationCase.class));
  }

  /**
   * 发送普通消息
   */
  public void sendNormalMessage(String id, List<ArbitrationCaseUser> acuList, String status) {
    new Thread(() -> {
      acuList.forEach(acu -> {
        this.addUserMessage(id, acu.getUserId(), null, "1", status, status);
      });
    }).start();
  }

  /**
   * 发送短信和邮件
   */
  public void sendSMSAndMail(String id, String caseNo, SMSEnum smse, String[] userType,
      boolean isFile, String fileType) {
    new Thread(() -> {
      if (isFile) {
        this.createFile(id, fileType);
      }
      List<ArbitrationCaseUserResponseDTO> acuList = arbitrationCaseUserMapper
          .getArbitrationCaseUserListForType(id,
              userType);
      acuList.forEach(arbitrationCaseUser -> {
        Map<String, String> data = new HashMap<>();
        data.put("caseNo", caseNo);
        // 短信发送接口
        smsService.send(arbitrationCaseUser.getMobilePhone(), smse, data);

        Email email = new Email();
        email.setEmail(arbitrationCaseUser.getEmail().split(","));
        email.setSubject("");
        email.setContent("");
        mailServiceImpl.send(email);
      });
    }).start();
  }

  /**
   * 插入消息
   */
  public void addUserMessage(String caseId, String receiverId, String docType, String messageType,
      String messageTitle,
      String messageContent) {
    UserMessage um = new UserMessage();
    um.setId(CommonsUtils.get32BitUUID());
    um.setCaseId(caseId);
    um.setReceiverId(receiverId);
    um.setMessageType(messageType);
    um.setDocType(docType);
    um.setRead("0");
    um.setMessageTitle(messageTitle);
    um.setMessageContent(messageContent);
    userMessageServiceImpl.insertUserMessage(um);
  }

  /**
   * 生成文书
   */
  private void createFile(String caseId, String docType) {
    documentCreateServiceImpl.createDocument(caseId, docType);
  }

  /**
   * 插入案件进度详情表
   */
  public void addCaseLog(String caseId, String caseStatus, String content, String userType) {
    new Thread(() -> {
      ArbitrationCaseLog acl = new ArbitrationCaseLog();
      acl.setId(CommonsUtils.get32BitUUID());
      acl.setCaseId(caseId);
      acl.setUserType(userType);
      acl.setContent(content);
      acl.setCaseStatus(caseStatus);
      arbitrationCaseLogMapper.insert(acl);
    }).start();
  }

  @Override
  public List<CaseStatus> selectCaseStatus(Integer userType) {
    Example csExample = new Example(CaseStatus.class, false);
    csExample.createCriteria().andEqualTo("userType", userType).andEqualTo("isShow", "0");
    csExample.orderBy("showOrder");
    return caseStatusMapper.selectByExample(csExample);
  }

  @Override
  public List<CaseStatus> selectCaseStatus() {
    List<CaseStatus> disputeRequestDTOList = new ArrayList<>();
    for (ArbitrationCaseStatusEnum e : ArbitrationCaseStatusEnum.values()) {
      CaseStatus caseStatusDTO = new CaseStatus();
      caseStatusDTO.setStatusCode(e.getCode());
      caseStatusDTO.setStatusName(e.getName());
      disputeRequestDTOList.add(caseStatusDTO);
    }
    return disputeRequestDTOList;
  }

  @Override
  public CaseUserEditQueryResponseDTO selectCaseUser(String id) {
    CaseUserEditQueryResponseDTO cueq = new CaseUserEditQueryResponseDTO();
    String[] user = {CaseUserTypeEnum.APPLICANT.getCode(), CaseUserTypeEnum.RESPONDENT.getCode(),
        CaseUserTypeEnum.AGENT_APPLICANT.getCode(),
        CaseUserTypeEnum.AGENT_RESPONDENT.getCode()};
    cueq.setArbitrationCaseUserList(
        arbitrationCaseUserMapper.getArbitrationCaseUserListAll(id, user));

    Example caseUserRelationExample = new Example(CaseUserRelation.class, false);
    caseUserRelationExample.createCriteria().andEqualTo("caseId", id).andEqualTo("status", "0");
    cueq.setCaseUserRelationList(caseUserRelationMapper.selectByExample(caseUserRelationExample));
    return cueq;
  }

  @Override
  public int updateCaseUser(String[] ids) {
    return arbitrationCaseUserMapper.updateAddUserStatus(ids);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public int deleteCaseUser(String[] ids) {
    List<String> proxyIdList = new ArrayList<>();
    final String[] caseId = {null};
    String[] proxy = {CaseUserTypeEnum.AGENT_APPLICANT.getCode(),
        CaseUserTypeEnum.AGENT_RESPONDENT.getCode()};
    Example arbitrationCaseUserExample = new Example(ArbitrationCaseUser.class, false);
    arbitrationCaseUserExample.createCriteria().andIn("id", Arrays.asList(ids))
        .andIn("userType", Arrays.asList(proxy));
    arbitrationCaseUserMapper.selectByExample(arbitrationCaseUserExample)
        .forEach(arbitrationCaseUser -> {
          proxyIdList.add(arbitrationCaseUser.getUserId());
          caseId[0] = arbitrationCaseUser.getCaseId();
        });
    if (!proxyIdList.isEmpty()) {
      Example caseUserRelationExample = new Example(CaseUserRelation.class, false);
      caseUserRelationExample.createCriteria().andEqualTo("caseId", caseId[0])
          .andIn("proxyId", proxyIdList);
      caseUserRelationMapper.deleteByExample(caseUserRelationExample);
    }
    return arbitrationCaseUserMapper.deleteAddUserStatus(ids);
  }

}
